package com.liuwa.social.http;

import com.alibaba.fastjson.JSONObject;
import com.liuwa.social.exception.SimpleRuntimeException;
import com.liuwa.social.config.JsonMapper;
import com.liuwa.social.exception.WeixinAccessTokenException;
import com.liuwa.social.exception.WeixinException;
import com.liuwa.social.weixin.utils.WeixinUtils;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.ParseException;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.CookieStore;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.cookie.Cookie;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.BasicCookieStore;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 简易http请求
 * @author rubekid
 * @date 2016年10月11日
 */
public class WeixinHttpClient {
	
	private static final Logger LOGGER = LoggerFactory.getLogger(WeixinHttpClient.class);

	private static CloseableHttpClient httpClient;
	
	private static CookieStore cookieStore;

	static {
		cookieStore  = new BasicCookieStore();

		// 将CookieStore设置到httpClient中
		httpClient = HttpClients.custom().setDefaultCookieStore(cookieStore).build();
	}
	
	public static String getCookie(String name){
		List<Cookie> cookies =  cookieStore.getCookies();
		for(Cookie cookie : cookies){
			if(cookie.getName().equalsIgnoreCase(name)){
				return cookie.getValue();
			}
		}
		return null;
		
	}
	
	/**
	 * GET 请求
	 * @param url
	 * @return
	 * @throws ClientProtocolException
	 * @throws IOException
	 */
	public static String get(String url){
		return get(url, null);
	}

	/**
	 * GET 请求
	 * @param url
	 * @return
	 * @throws ClientProtocolException
	 * @throws IOException
	 */
	public static String get(String url, Map<String, String> headers){
		try {
			HttpGet httpGet = new HttpGet(url);
			httpGet.setHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.90 Safari/537.36");
			if(headers != null){
				addHeaders(httpGet, headers);
			}
			HttpResponse httpResponse = httpClient.execute(httpGet);
			String content = EntityUtils.toString(httpResponse.getEntity());
			LOGGER.info("响应内容：{}", content);
			JSONObject respJson = JSONObject.parseObject(content);
			if(respJson.containsKey("errcode") && respJson.getInteger("errcode") != 0){
				if(respJson.getInteger("errcode") == 40001){
					throw new WeixinAccessTokenException(respJson.getString("errmsg"));
				}
				throw new WeixinException(respJson.getString("errmsg"));
			}
			return content;
		} catch (ParseException | IOException ex) {
			LOGGER.error(ex.getMessage(), ex);
		}
		return "";
	}

	/**
	 * POST 请求
	 * @param url
	 * @param params
	 * @param headers
	 * @return
	 */
	public static String post(String url, Map<String, Object> params, Map<String, String> headers){
		try {
			HttpPost httpPost = new HttpPost(url);
			UrlEncodedFormEntity postEntity = new UrlEncodedFormEntity(getParam(params), "UTF-8");
			httpPost.setEntity(postEntity);
			httpPost.setHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.90 Safari/537.36");
			if(headers != null){
				addHeaders(httpPost, headers);
			}
			HttpResponse httpResponse = httpClient.execute(httpPost);
			String content =  EntityUtils.toString(httpResponse.getEntity(), "UTF-8");
			LOGGER.info("响应内容：{}", content);
			JSONObject respJson = JSONObject.parseObject(content);
			if(respJson.containsKey("errcode") && respJson.getInteger("errcode") != 0){
				if(respJson.getInteger("errcode") == 40001){
					throw new WeixinAccessTokenException(respJson.getString("errmsg"));
				}
				throw new WeixinException(respJson.getString("errmsg"));
			}
			return content;
		} catch (ParseException | IOException ex) {
			LOGGER.error(ex.getMessage(), ex);
		}
		return "";
		
	}
	
	/**
	 * POST 请求
	 * @param url
	 * @param url
	 * @param body
	 * @return
	 */
	public static String post(String url, JSONObject body){
		try {
			HttpPost httpPost = new HttpPost(url);
			StringEntity entity = new StringEntity(body.toString(),"utf-8");
			entity.setContentEncoding("UTF-8");    
			entity.setContentType("application/json");    
			httpPost.setEntity(entity);
			httpPost.setHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.90 Safari/537.36");

			HttpResponse httpResponse = httpClient.execute(httpPost);
			String content =  EntityUtils.toString(httpResponse.getEntity(), "UTF-8");
			LOGGER.info("响应内容：{}", content);
			JSONObject respJson = JSONObject.parseObject(content);
			if(respJson.containsKey("errcode") && respJson.getInteger("errcode") != 0){
				if(respJson.getInteger("errcode") == 40001){
					throw new WeixinAccessTokenException(respJson.getString("errmsg"));
				}
				throw new WeixinException(respJson.getString("errmsg"));
			}
			return content;
		} catch (ParseException | IOException ex) {
			LOGGER.error(ex.getMessage(), ex);
		}
		return "";
		
	}

	/**
	 * post 请求
	 * @param url
	 * @param body
	 * @return
	 */
	public static byte[] postForByte(String url, JSONObject body){
		try {
			HttpPost httpPost = new HttpPost(url);
			StringEntity entity = new StringEntity(body.toString(),"utf-8");
			entity.setContentEncoding("UTF-8");
			entity.setContentType("application/json");
			httpPost.setEntity(entity);
			httpPost.setHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.90 Safari/537.36");

			HttpResponse httpResponse = httpClient.execute(httpPost);
			return EntityUtils.toByteArray(httpResponse.getEntity());
		} catch (ParseException | IOException ex) {
			LOGGER.error(ex.getMessage(), ex);
		}
		return null;
	}
	
	/**
	 * POST 请求
	 * @param url
	 * @return
	 * @throws ParseException
	 * @throws IOException
	 */
	public static String post(String url){
		Map<String, Object> params = new HashMap<String, Object>();
		return post(url, params, null);
	}
	
	/**
	 * 获取数据并转成对象
	 * @param url
	 * @param clazz
	 * @return
	 */
	public static <T> T getForObject(String url, Class<T> clazz){
		String resp = get(url);
		try{
			return toBean(resp, clazz);
		}
		catch(SimpleRuntimeException ex){
			System.out.println("响应内容:" + resp);
			LOGGER.error(ex.getMessage(), ex);
		}
		return null;
	}
	
	/**
	 * 获取数据并转成对象
	 * @param url
	 * @param clazz
	 * @param headers
	 * @return
	 */
	public static <T> T getForObject(String url, Class<T> clazz, Map<String, String> headers){
		try{
			return toBean(get(url, headers), clazz);
		}
		catch(SimpleRuntimeException ex){
			LOGGER.error(ex.getMessage(), ex);
		}
		return null;
	}
	
	/**
	 * 获取数据并转成对象
	 * @param url
	 * @param clazz
	 * @return
	 */
	public static <T> T postForObject(String url, Class<T> clazz){
		try{
			return toBean(post(url), clazz);
		}
		catch(SimpleRuntimeException ex){
			LOGGER.error(ex.getMessage(), ex);
		}
		return null;
	}
	
	/**
	 * 获取数据并转成对象
	 * @param url
	 * @param clazz
	 * @return
	 */
	public static <T> T postForObject(String url, JSONObject body,  Class<T> clazz){
		try{
			return toBean(post(url, body), clazz);
		}
		catch(SimpleRuntimeException ex){
			LOGGER.error(ex.getMessage(), ex);
		}
		return null;
	}

	/**
	 * 请求参数
	 * @param parameterMap
	 * @return
	 */
	private static List<NameValuePair> getParam(Map<String, Object> parameterMap) {
		List<NameValuePair> param = new ArrayList<NameValuePair>();
		for(Map.Entry<String, Object> entry : parameterMap.entrySet()){
			param.add(new BasicNameValuePair(entry.getKey(), String.valueOf(entry.getValue())));
		}
		return param;
	}
	
	/**
	 * 添加请求头部
	 * @param httpRequest
	 * @param headerMap
	 */
	private static void addHeaders(HttpRequestBase httpRequest, Map<String, String> headerMap){
		for(Map.Entry<String, String> entry : headerMap.entrySet()){
			httpRequest.addHeader(entry.getKey(), entry.getValue());
		}
	}
	
	/**
	 * 文本转换成BEAN
	 * @param response
	 * @param clazz
	 * @return
	 */
	private static <T> T toBean(String response, Class<T> clazz){
		MappingJackson2HttpMessageConverter messageConverter = new MappingJackson2HttpMessageConverter();
        messageConverter.setObjectMapper(JsonMapper.getMapper());
		return messageConverter.getObjectMapper().convertValue(JSONObject.parseObject(TextDecode(response)), clazz);
	}
	
	
	/**
	 * 转码
	 * @param str
	 * @return
	 */
	private static String TextDecode(String str){

		if(str!=null && !Charset.forName("GBK").newEncoder().canEncode(str)){
			
			try {
				str = new String(str.getBytes("ISO-8859-1"), "utf-8");
			} catch (UnsupportedEncodingException e) {
				e.printStackTrace();
			}
		}
		
		return str;
	}
}
